/*
 * CS_PVP_ROOM_JOIN.cpp
 *
 *  Created on: 2014. 1. 6.
 *      Author: mega
 */

#include "../../User.h"
#include "../../Command.h"
#include "../../NLogic/Space.h"
#include "../../NLogic/Party.h"
#include "../../NLogic/Equip.h"
#include "../../NLogic/Buff.h"
#include "../../NLogic/SocialInfo.h"
#include "../../NLogic/Static.h"

namespace ProjectZ { namespace NCommand {

void SendFailPVPRoomJoin(User * pUser, int ack)
{
	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();

	*pAck << static_cast<int16_t>(ack);

	pAck->MakePacket(CMD_SC_PVP_ROOM_JOIN);
	pUser->Send(pAck);
}

void SendOKPVPRoomJoin(User * pUser, User * pOppUser, int roomNumber)
{
	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();

	*pAck << static_cast<int16_t>(ACK_OK);
	*pAck << static_cast<uint32_t>(roomNumber);
	*pAck << static_cast<uint16_t>(pUser->GetCharacterInfo().consecutive_win);		// 본인 연승 정보
	*pAck << pOppUser->GetSocialID().c_str();										// 상대방 카카오톡 ID

	NLogic::SocialInfo * pSocialInfo = pOppUser->GetSocialInfo();
	if (NULL == pSocialInfo)
	{
		::Network::GETPACKETPOOL()->SEND_DEL(pAck);
		DEBUGLOG("SendOKPVPRoomJoin : pSocialInfo is NULL!!");
		return;
	}

	if (1 == pSocialInfo->GetData()->_profile_opened)
	{
		*pAck << pOppUser->GetUserInfo().nickname.c_str();							// 상대방 카카오톡 닉네임
	}
	else
	{
		*pAck << static_cast<uint16_t>(0);
	}

	*pAck << pOppUser->GetCharacterInfo().characterseq;		// 캐릭터 Seq
	*pAck << pOppUser->GetUserInfo().profile_url.c_str();	// 상대방 Profile URL
	*pAck << static_cast<uint16_t>(pOppUser->GetCharacterInfo().level);
	*pAck << static_cast<uint8_t>(pOppUser->GetCharacterInfo().classtype);

	// 전투펫 TID
	NLogic::Equip * pOppEquip = pOppUser->GetEquip();
	NLogic::Item * pItem = pOppEquip->GetItem(ITEM_EQUIP_POS_PET);
	if (pItem == NULL)
	{
		*pAck << static_cast<int16_t>(-1);
	}
	else
	{
		*pAck << static_cast<int16_t>(pItem->GetData().tid);
	}

	*pAck << static_cast<int8_t>(-1);		// 길드
	*pAck << static_cast<int16_t>(0);		// 길드 이름
	*pAck << pOppUser->GetUserSeq();


	// 사용되고 있는 버프 갯수
	NLogic::Buff * pBuff = pOppUser->GetBuff();
	if (NULL == pBuff)
	{
		::Network::GETPACKETPOOL()->SEND_DEL(pAck);
		DEBUGLOG("SendOKPVPRoomJoin : pBuff is NULL!!");
		return;
	}

	std::time_t t = std::time(0);  // t is an integer type
	unsigned int nTime = t;

//	*pAck << static_cast<uint8_t>(pBuff->GetDataVector().size());
	*pAck << static_cast<uint8_t>(pBuff->GetActiveBuffCount(nTime));

	std::for_each(pBuff->GetDataVector().begin(), pBuff->GetDataVector().end(), [&](NLogic::Buff::Data * pData) {

		if (pData->u8type == static_cast<int>(NLogic::Buff::BuffType::GUILD))
		{
			* pAck << static_cast<uint8_t>(pData->u8type);
			* pAck << static_cast<uint16_t>(pData->u16skill_tid);
			* pAck << static_cast<uint8_t>(pData->u8skill_level);
			* pAck << static_cast<uint16_t>(pData->s16skill_value);
			* pAck << static_cast<uint16_t>(pData->_regdate);
		}
		else
		{
			if (pData->_regdate < nTime)
			{
				pData->Clear();
			}
			else
			{
				* pAck << static_cast<uint8_t>(pData->u8type);
				* pAck << static_cast<uint16_t>(pData->u16skill_tid);
				* pAck << static_cast<uint8_t>(pData->u8skill_level);
				* pAck << static_cast<uint16_t>(pData->s16skill_value);
				* pAck << static_cast<uint16_t>(pData->_regdate - nTime);
			}
		}
	} );

	pAck->MakePacket(CMD_SC_PVP_ROOM_JOIN);
	pUser->Send(pAck);
}

void Command::CS_PVP_ROOM_JOIN(User * pUser, ::Network::Packet * pPacket)
{
/*	CS_PVP_ROOM_JOIN			0x1325
	{
		u32	u32room_number;
	}

	SC_PVP_ROOM_JOIN			0x1326
	{
		s16				s16ack;
		u32				u32room_number;
		u16				u16Victory_count;			//본인 연승 정보
		str				strUser_id;		 			//상대방 카톡 ID
		str				strUser_Nickname;		 	//상대방 카톡 닉네임
		u32				u32slot_seq;				//캐릭터 고유 DB인덱스
		str				strProfile_url;				//프로필 url
		u16				u16Level;					//레벨
		u8				u8Class_type;				//클래스
		s16				s16Pet_tid;					//전투펫 TID (-1: 없음)
		s8				s8Guild_icon;				//길드 계급 아이콘 번호 ( -1: 길드 없음 )
		str				strGuild_name;		 		//길드 이름
		u32				u32userseq;					//userseq

		/// 버프관련
		u8 				u8use_buff_count;			//사용되고 있는 버프 갯수
		{
			u8 u8type;						/// 0:승점버프, 1:친구버프, 2:참피온 버프1 , 3:참피온 버프2, 4:길드 버프
			u16	u16skill_tid;
			u8 u8skill_level;
			s16	s16skill_value;
			u16	u16skill_time;
		}
	}*/

	PREPARE_PACKET;

	uint32_t roomNumber;

	*pPacket >> roomNumber;

	if (static_cast<int>(roomNumber) > MAX_NEW_PVP_ROOM)
	{
		DEBUGLOG("%s : INVALID PVP ROOM NUMBER.", __FUNCTION__);
		SendFailPVPRoomJoin(pUser, ACK_UNKNOWN_ERROR);
		return;
	}

	NLogic::Space * pWorld = pUser->GetSpace();
	if (NULL == pWorld)
	{
		DEBUGLOG("%s : pWorld is NULL!!", __FUNCTION__);
		SendFailPVPRoomJoin(pUser, ACK_NO_SPACE);
		return;
	}

	if (pWorld->GetData()._spaceType != NLogic::Space::SpaceType::WORLD)
	{
		DEBUGLOG("%s : User Space is Not World!", __FUNCTION__);
		SendFailPVPRoomJoin(pUser, ACK_NO_SPACE);
		return;
	}

	if (pUser->GetEnumState() != User::EnumState::__NONE__)
	{
		DEBUGLOG("%s : User Status is Not Normal!!", __FUNCTION__);
		SendFailPVPRoomJoin(pUser, ACK_UNKNOWN_ERROR);
		return;
	}

	NLogic::Equip * pEquip = pUser->GetEquip();
	if (NULL == pEquip)
	{
		DEBUGLOG("%s : pEquip is NULL!!", __FUNCTION__);
		SendFailPVPRoomJoin(pUser, ACK_UNKNOWN_ERROR);
		return;
	}


	NLogic::Static::SPACEVECTOR & clsPVPRoomVector = NLogic::Static::InstancePtr()->GETPVPROOMVECTOR();

	NLogic::Space * pPVPRoomSpace = NULL;

	auto spaceIter = clsPVPRoomVector.begin();
	for (; spaceIter != clsPVPRoomVector.end(); ++spaceIter)
	{
		NLogic::Space * pOpenSpace	= ( * spaceIter );
		NLogic::IndexerPVP * pPVPIndex	= pOpenSpace->GetPVPIndexer();
		if (NULL == pPVPIndex)
			continue;

		if (static_cast<int>(roomNumber) == pPVPIndex->GetIndex())
		{
			pPVPRoomSpace = pOpenSpace;
			break;
		}
	}

	if (NULL == pPVPRoomSpace)
	{
		DEBUGLOG("%s : pPVPRoomSpace is NULL!!", __FUNCTION__);
		SendFailPVPRoomJoin(pUser, ACK_PVP_PK_NOT_EXIST_ROOM);
		return;
	}

	NLogic::Party * pPVPRoomParty = pPVPRoomSpace->GetParty();
	if (NULL == pPVPRoomParty)
	{
		DEBUGLOG("%s : pPVPRoomParty is NULL!!", __FUNCTION__);
		SendFailPVPRoomJoin(pUser, ACK_PVP_PK_NOT_EXIST_ROOM);
		return;
	}

	User * pMaster = pPVPRoomParty->GetMaster();
	if (NULL == pMaster)
	{
		DEBUGLOG("%s : pMaster is NULL!!", __FUNCTION__);
		SendFailPVPRoomJoin(pUser, ACK_PVP_PK_NOT_EXIST_ROOM);
		return;
	}

	NLogic::Equip * pMasterEquip = pMaster->GetEquip();
	if (NULL == pMasterEquip)
	{
		DEBUGLOG("%s : pMasterEquip is NULL!!", __FUNCTION__);
		SendFailPVPRoomJoin(pUser, ACK_UNKNOWN_ERROR);
		return;
	}

	// 대전이 이미 시작 된 경우
	if (pPVPRoomParty->GetState() != NLogic::Party::State::NEW_PVP_ROOM_ACCEPT_WAIT)
	{
		SendFailPVPRoomJoin(pUser, ACK_PVP_PK_START_BATTLE);
		return;
	}

	// 월드에서 제거하고, PVP 입장
	pWorld->LeaveUser(pUser);
	pPVPRoomParty->EnterUser(pUser);
	pPVPRoomSpace->EnterUser(pUser);

	// 유저의 좌표 설정
	pUser->SetCoordinate(PVP_P1_START_X, PVP_P1_START_Y);
	pMaster->SetCoordinate(PVP_P2_START_X, PVP_P2_START_Y, 180);

	pUser->GetBattle()->GetData().bReadyFight = false;
	pMaster->GetBattle()->GetData().bReadyFight = false;

	// 각각 상대방 설정
	pUser->GetBattle()->GetData()._pvpOppUser = pMaster;
	pMaster->GetBattle()->GetData()._pvpOppUser = pUser;

//	pMaster->UpdateLatency();
//	pUser->UpdateLatency();

	pPVPRoomSpace->MakePVPResultData(pUser, pMaster);
	pPVPRoomSpace->MakePVPResultData(pMaster, pUser);

	// 전투펫을 장착하고 있다면 스태미너 감소
	if (true == pEquip->IsExistItem(ITEM_EQUIP_POS_PET))
	{
		pEquip->GetItem(ITEM_EQUIP_POS_PET)->DecreaseBattlepetStamina();
	}

	if (true == pMasterEquip->IsExistItem(ITEM_EQUIP_POS_PET))
	{
		pMasterEquip->GetItem(ITEM_EQUIP_POS_PET)->DecreaseBattlepetStamina();
	}

	// 응답
	SendOKPVPRoomJoin(pUser, pMaster, roomNumber);
	SendOKPVPRoomJoin(pMaster, pUser, roomNumber);

	// Party 상태 변경
	pPVPRoomParty->SetState(NLogic::Party::State::PVP_ENTERROOM_WAIT);
}

} /*NCommand*/ } /*ProjectZ*/
